/*
 * BGSubstraction.cpp
 *
 *  Created on: Mar 31, 2010
 *      Author: Víctor Gaspar
 *
 *  NOTES: Todos los comentarios los dejo para que
 *  se pueda probar a posteriori paso a paso
 */

#include <cv.h>
#include <cvaux.h>
#include <highgui.h>
#include <stdio.h>
#include <sstream>
#include <sys/stat.h>

std::string BGPATH;
std::string LSTPATH;
std::string FMPATH;

int contador;

bool FileExists(std::string strFilename) {
  struct stat stFileInfo;
  bool blnReturn;
  int intStat;

  // Attempt to get the file attributes
  intStat = stat(strFilename.c_str(),&stFileInfo);
  if(intStat == 0)
    blnReturn = true;
  else
    blnReturn = false;

  return(blnReturn);
}

void buscarMayorArea(CvPoint point, IplImage * image) {
	IplImage* g_gray = NULL;
	CvMemStorage* g_storage = NULL;

	if (g_storage == NULL) {
		g_gray = cvCreateImage(cvGetSize(image), 8, 1);
		g_storage = cvCreateMemStorage(0);
	} else {
		cvClearMemStorage(g_storage);
	}

	CvSeq* contours = 0;
	cvFindContours(image, g_storage, &contours);
	cvZero(g_gray);

	contador = 0;
	for (CvSeq* c = contours; c != NULL; c = c->h_next) {

		if (c->first->count > 10) {
			cvDrawContours(image, c, CV_RGB(0,255,0),CV_RGB(255,255,0), -1, 1, 8);
			//	contours[contador] = NULL;
			contador++;
		}

	}

	//printf("Contador de coches=%d \n", contador);
	/*
	int maxLevel = 3;
	CvTreeNodeIterator iterator;
	CvPoint pt;
	if (contours != 0)
		cvInitTreeNodeIterator(&iterator, contours, maxLevel);
	int i = 0;

	while ((contours = (CvSeq*) cvNextTreeNode(&iterator)) != 0) {
		CvSeqReader reader;
		int count = contours->total;
		cvStartReadSeq(contours, &reader, 0);
		count -= !CV_IS_SEQ_CLOSED ( contours );
		CV_READ_SEQ_ELEM ( pt, reader );
		i++;
		////ptArray[i] = pt;
		//CvScalar s = cvGet2D(image, pt.y, pt.x);

		if (s.val[0] == 0) {
			printf("coordinates%d: %d %d \n", i, pt.x, pt.y);
			cvRectangle(image, pt, cvPoint(pt.x + 2, pt.y + 2), CV_RGB(255,0,0), 1, 8, 0);
		}
	}*/

}

// Foreground and Background extraction
int main(int argc, char* argv[]) {

	if(argc > 4)
	{
		printf("Too many arguments supplied.\n");
		exit(0);
	} else if (argc < 4){
		printf("Too few arguments supplied.\n");
		exit(0);
	}

	BGPATH = argv[1];
	LSTPATH = argv[2];
	FMPATH = argv[3];

	IplImage* bg_image = cvLoadImage(BGPATH.c_str());
	IplImage* bg_image_smooth = cvCreateImage(cvSize(bg_image->width,bg_image->height), 8, 3);
	IplImage* bg_image_hsl = cvCreateImage(cvSize(bg_image->width,bg_image->height), 8, 3);

	if (!bg_image) {
		printf("bad image \n");
		exit(0);
	}

	cvSmooth(bg_image, bg_image_smooth, CV_GAUSSIAN, 5, 5);
	cvCvtColor(bg_image_smooth, bg_image_hsl, CV_RGB2Luv);

	//cvNamedWindow("BG", 1);
	cvNamedWindow("FG", 1);
	//cvNamedWindow("IMG", 1);

	//create BG model
	CvBGStatModel* bg_model = cvCreateGaussianBGModel(bg_image_hsl);

	if(FileExists(LSTPATH))
	{
		IplImage* lst_image = cvLoadImage(LSTPATH.c_str());
		IplImage* lst_image_smooth = cvCreateImage(cvSize(lst_image->width,bg_image->height), 8, 3);
		IplImage* lst_image_hsl = cvCreateImage(cvSize(lst_image->width,lst_image->height), 8, 3);

		cvSmooth(lst_image, lst_image_smooth, CV_GAUSSIAN, 5, 5);
		cvCvtColor(lst_image_smooth, lst_image_hsl, CV_RGB2Luv);

		// Update model
		cvUpdateBGStatModel(lst_image_hsl, bg_model);

		// show images
		//cvShowImage("BG", bg_model->background);
		//cvShowImage("FG", bg_model->foreground);
		//cvShowImage("IMG", lst_image_hsl);

		//cvWaitKey();

		cvReleaseImage(&lst_image_hsl);
		cvReleaseImage(&lst_image_smooth);
		cvReleaseImage(&lst_image);
	}else{
		exit(0);
	}

	//cvSaveImage("/home/victor/Development/traffiCVision/fg_sample.jpg", bg_model->foreground);

	// Aquí el FG lo tenemos calculado
	IplImage* image = bg_model->foreground;
	IplImage* imageFilter = cvLoadImage(FMPATH.c_str(), 1);

	//Inicialización para acceder a los píxeles
	CvScalar s;
	CvScalar f;
	 // get the (i,j) pixel value

	int blancos = 0, negros = 0;
	//Contamos los píxeles negros y blancos
	for (int i=0; i<image->width ; i++)
		for (int j=0; j<image->height; j++) {
			f = cvGet2D(imageFilter,j,i);
			s = cvGet2D(image,j,i);

			if ( f.val[0] == 0 ){
				cvSet2D(image,j,i,f);
				s.val[0] = 0;
			}
			if ( s.val[0] == 0 )
				negros++;
			else
				blancos++;
		}
	//printf("Blancos=%d , Negros=%d \n",blancos, negros);
	buscarMayorArea(CvPoint(), image);

	// Liberamos todos los recursos
	cvReleaseImage(&image);
	cvReleaseImage(&imageFilter);

	cvReleaseImage(&bg_image_hsl);
	cvReleaseImage(&bg_image_smooth);
	cvReleaseImage(&bg_image);

	// Devolvemos el número de coches
	printf("%d", contador);

	return 0;
}

